<template>
  <q-page class="q-pa-md">
    <!-- 查询和操作区域 -->
    <q-card flat bordered class="q-mb-md">
      <q-card-section class="row items-center">
        <div class="text-h6">文件管理</div>
        <q-space />
        <q-btn color="primary" label="上传文件" icon="cloud_upload" @click="uploadDialog = true" />
      </q-card-section>

      <q-card-section>
        <div class="row q-col-gutter-md">
          <q-input
            v-model="searchForm.fileName"
            label="文件名称"
            outlined
            dense
            clearable
            class="col-md-4 col-sm-6 col-xs-12"
          />
          <q-input
            v-model="searchForm.uploader"
            label="上传人"
            outlined
            dense
            clearable
            class="col-md-4 col-sm-6 col-xs-12"
          />
          <q-select
            v-model="searchForm.fileType"
            label="文件类型"
            :options="fileTypeOptions"
            outlined
            dense
            emit-value
            map-options
            class="col-md-4 col-sm-6 col-xs-12"
          />
          <div class="col-md-12 flex justify-end">
            <q-btn color="primary" label="查询" @click="handleSearch" class="q-mr-sm" />
            <q-btn label="重置" outline color="primary" @click="resetSearch" />
          </div>
        </div>
      </q-card-section>
    </q-card>

    <!-- 文件列表 -->
    <q-card flat bordered>
      <q-table
        :rows="files"
        :columns="columns"
        row-key="fileId"
        :loading="loading"
        :pagination="pagination"
        @request="onRequest"
        binary-state-sort
        flat
        bordered
      >
        <!-- 文件类型列 -->
        <template v-slot:body-cell-fileType="props">
          <q-td :props="props">
            <q-icon :name="getFileTypeIcon(props.row.fileType)" size="24px" />
            <span class="q-ml-sm">{{ props.row.fileType }}</span>
          </q-td>
        </template>

        <!-- 文件大小列 -->
        <template v-slot:body-cell-fileSize="props">
          <q-td :props="props">
            {{ formatFileSize(props.row.fileSize) }}
          </q-td>
        </template>

        <!-- 操作列 -->
        <template v-slot:body-cell-actions="props">
          <q-td :props="props" class="q-gutter-x-sm">
            <q-btn dense color="primary" icon="visibility" @click="previewFile(props.row)">
              <q-tooltip>预览</q-tooltip>
            </q-btn>
            <q-btn dense color="secondary" icon="download" @click="downloadFile(props.row)">
              <q-tooltip>下载</q-tooltip>
            </q-btn>
            <q-btn dense color="negative" icon="delete" @click="confirmDelete(props.row.fileId)">
              <q-tooltip>删除</q-tooltip>
            </q-btn>
          </q-td>
        </template>
      </q-table>
    </q-card>

    <!-- 文件上传对话框 -->
    <q-dialog v-model="uploadDialog" persistent>
      <q-card style="min-width: 500px">
        <q-card-section>
          <div class="text-h6">上传文件</div>
        </q-card-section>

        <q-card-section>
          <q-uploader
            ref="uploader"
            :url="uploadUrl"
            label="选择文件或拖拽到此处"
            multiple
            :max-files="5"
            :max-file-size="10 * 1024 * 1024"
            @rejected="onRejected"
            @uploaded="onUploaded"
            :form-fields="uploadFormFields"
            style="width: 100%"
          >
            <template v-slot:list="scope">
              <q-list separator>
                <q-item v-for="file in scope.files" :key="file.name">
                  <q-item-section>
                    <q-item-label>{{ file.name }}</q-item-label>
                    <q-item-label caption> 大小: {{ formatFileSize(file.size) }} </q-item-label>
                  </q-item-section>

                  <q-item-section side>
                    <q-spinner v-if="file.uploading" class="q-uploader__spinner" />
                    <q-btn v-else round dense flat icon="cancel" @click="scope.removeFile(file)" />
                  </q-item-section>
                </q-item>
              </q-list>
            </template>
          </q-uploader>
        </q-card-section>

        <q-card-actions align="right">
          <q-btn label="取消" v-close-popup flat color="primary" />
          <q-btn label="开始上传" color="primary" @click="startUpload" />
        </q-card-actions>
      </q-card>
    </q-dialog>

    <!-- 文件预览对话框 -->
    <q-dialog v-model="previewDialog" maximized>
      <q-card>
        <q-bar class="bg-primary text-white">
          <div class="text-h6">{{ previewFileInfo.fileName }}</div>
          <q-space />
          <q-btn dense flat icon="close" v-close-popup />
        </q-bar>

        <q-card-section class="q-pa-none full-height">
          <div v-if="isImage(previewFileInfo.fileType)" class="full-height flex flex-center">
            <q-img
              :src="previewFileInfo.fileUrl"
              spinner-color="primary"
              style="max-width: 100%; max-height: 100%"
            />
          </div>

          <div v-else-if="isVideo(previewFileInfo.fileType)" class="full-height flex flex-center">
            <video controls style="max-width: 100%; max-height: 100%">
              <source :src="previewFileInfo.fileUrl" :type="previewFileInfo.fileType" />
              您的浏览器不支持视频播放
            </video>
          </div>

          <div v-else-if="isAudio(previewFileInfo.fileType)" class="full-height flex flex-center">
            <audio controls style="width: 80%">
              <source :src="previewFileInfo.fileUrl" :type="previewFileInfo.fileType" />
              您的浏览器不支持音频播放
            </audio>
          </div>

          <div v-else-if="isPdf(previewFileInfo.fileType)" class="full-height">
            <embed
              :src="previewFileInfo.fileUrl"
              type="application/pdf"
              width="100%"
              height="100%"
            />
          </div>

          <div v-else class="full-height flex flex-center column">
            <q-icon name="insert_drive_file" size="xl" />
            <div class="q-mt-md">不支持在线预览，请下载查看</div>
            <q-btn
              label="下载文件"
              color="primary"
              icon="download"
              class="q-mt-md"
              @click="downloadFile(previewFileInfo)"
            />
          </div>
        </q-card-section>
      </q-card>
    </q-dialog>
  </q-page>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { useQuasar } from 'quasar'

const $q = useQuasar()

// 表格列定义
const columns = [
  { name: 'fileName', label: '文件名称', field: 'fileName', align: 'left', sortable: true },
  { name: 'fileType', label: '文件类型', field: 'fileType', align: 'center' },
  { name: 'fileSize', label: '文件大小', field: 'fileSize', align: 'center', sortable: true },
  { name: 'uploader', label: '上传人', field: 'uploader', align: 'center' },
  { name: 'uploadTime', label: '上传时间', field: 'uploadTime', align: 'center', sortable: true },
  { name: 'actions', label: '操作', align: 'center' },
]

// 文件类型选项
const fileTypeOptions = [
  { label: '全部', value: '' },
  { label: '图片', value: 'image' },
  { label: '文档', value: 'document' },
  { label: '视频', value: 'video' },
  { label: '音频', value: 'audio' },
  { label: '压缩包', value: 'archive' },
  { label: '其他', value: 'other' },
]

// 数据状态
const files = ref([])
const loading = ref(false)
const pagination = ref({
  page: 1,
  rowsPerPage: 10,
  rowsNumber: 0,
})
const searchForm = ref({
  fileName: '',
  uploader: '',
  fileType: '',
})

// 上传相关
const uploadDialog = ref(false)
const uploader = ref(null)
const uploadUrl = ref('/api/upload') // 替换为实际的上传接口
const uploadFormFields = ref([
  { name: 'bizType', value: 'default' },
  { name: 'uploader', value: 'admin' }, // 替换为实际的上传人
])

// 预览相关
const previewDialog = ref(false)
const previewFileInfo = ref({
  fileId: '',
  fileName: '',
  fileType: '',
  fileUrl: '',
})

// 文件类型图标映射
const fileTypeIcons = {
  // 图片
  'image/jpeg': 'image',
  'image/png': 'image',
  'image/gif': 'image',
  'image/bmp': 'image',
  'image/webp': 'image',
  'image/svg+xml': 'image',
  // 文档
  'application/pdf': 'picture_as_pdf',
  'application/msword': 'description',
  'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'description',
  'application/vnd.ms-excel': 'description',
  'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'description',
  'application/vnd.ms-powerpoint': 'description',
  'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'description',
  'text/plain': 'description',
  'text/csv': 'description',
  // 视频
  'video/mp4': 'movie',
  'video/webm': 'movie',
  'video/ogg': 'movie',
  'video/quicktime': 'movie',
  // 音频
  'audio/mpeg': 'audiotrack',
  'audio/ogg': 'audiotrack',
  'audio/wav': 'audiotrack',
  // 压缩包
  'application/zip': 'folder_zip',
  'application/x-rar-compressed': 'folder_zip',
  'application/x-7z-compressed': 'folder_zip',
  'application/x-tar': 'folder_zip',
  'application/gzip': 'folder_zip',
  // 默认
  default: 'insert_drive_file',
}

// 初始化加载数据
onMounted(() => {
  loadFiles()
})

// 加载文件列表
function loadFiles(props) {
  if (!props) {
    props = { pagination: pagination.value }
  }

  loading.value = true
  const { page, rowsPerPage } = props.pagination

  // 模拟API请求
  setTimeout(() => {
    // 这里应该是实际的API调用
    // 模拟数据
    const mockData = Array.from({ length: rowsPerPage }, (_, i) => ({
      fileId: (page - 1) * rowsPerPage + i + 1,
      fileName: [
        '产品介绍.pdf',
        '用户头像.jpg',
        '宣传视频.mp4',
        '年度报表.xlsx',
        '系统说明文档.docx',
      ][i % 5],
      fileType: [
        'application/pdf',
        'image/jpeg',
        'video/mp4',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
      ][i % 5],
      fileSize: [1024 * 1024 * 2, 512 * 1024, 10 * 1024 * 1024, 256 * 1024, 768 * 1024][i % 5],
      fileUrl:
        '/files/' + ['product.pdf', 'avatar.jpg', 'promo.mp4', 'report.xlsx', 'manual.docx'][i % 5],
      uploader: ['admin', 'user1', 'admin', 'user2', 'user3'][i % 5],
      uploadTime: new Date(Date.now() - i * 3600 * 1000).toLocaleString(),
    }))

    // 应用查询条件
    let filteredData = [...mockData]
    if (props.filter.fileName) {
      filteredData = filteredData.filter((item) => item.fileName.includes(props.filter.fileName))
    }
    if (props.filter.uploader) {
      filteredData = filteredData.filter((item) => item.uploader.includes(props.filter.uploader))
    }
    if (props.filter.fileType) {
      filteredData = filteredData.filter((item) => {
        if (props.filter.fileType === 'image') return item.fileType.startsWith('image/')
        if (props.filter.fileType === 'document')
          return (
            (item.fileType.startsWith('application/') &&
              !item.fileType.includes('vnd.openxmlformats') &&
              !item.fileType.includes('zip') &&
              !item.fileType.includes('pdf')) ||
            item.fileType === 'text/plain'
          )
        if (props.filter.fileType === 'video') return item.fileType.startsWith('video/')
        if (props.filter.fileType === 'audio') return item.fileType.startsWith('audio/')
        if (props.filter.fileType === 'archive')
          return (
            item.fileType.includes('zip') ||
            item.fileType.includes('rar') ||
            item.fileType.includes('7z') ||
            item.fileType.includes('tar') ||
            item.fileType.includes('gzip')
          )
        return true
      })
    }

    files.value = filteredData
    pagination.value.rowsNumber = filteredData.length
    pagination.value.page = page
    pagination.value.rowsPerPage = rowsPerPage
    loading.value = false
  }, 500)
}

// 表格请求方法
function onRequest(props) {
  loadFiles(props)
}

// 查询处理
function handleSearch() {
  pagination.value.page = 1
  onRequest({
    pagination: pagination.value,
    filter: searchForm.value,
  })
}

// 重置查询
function resetSearch() {
  searchForm.value = {
    fileName: '',
    uploader: '',
    fileType: '',
  }
  handleSearch()
}

// 获取文件类型图标
function getFileTypeIcon(fileType) {
  if (!fileType) return fileTypeIcons.default

  for (const [key, icon] of Object.entries(fileTypeIcons)) {
    if (fileType.startsWith(key.split('/')[0])) {
      return icon
    }
  }

  return fileTypeIcons.default
}

// 格式化文件大小
function formatFileSize(bytes) {
  if (bytes === 0) return '0 Bytes'

  const k = 1024
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))

  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// 文件类型判断
function isImage(fileType) {
  return fileType && fileType.startsWith('image/')
}

function isVideo(fileType) {
  return fileType && fileType.startsWith('video/')
}

function isAudio(fileType) {
  return fileType && fileType.startsWith('audio/')
}

function isPdf(fileType) {
  return fileType === 'application/pdf'
}

// 预览文件
function previewFile(file) {
  previewFileInfo.value = {
    fileId: file.fileId,
    fileName: file.fileName,
    fileType: file.fileType,
    fileUrl: file.fileUrl,
  }
  previewDialog.value = true
}

// 下载文件
function downloadFile(file) {
  // 这里应该是实际的下载逻辑
  const link = document.createElement('a')
  link.href = file.fileUrl
  link.download = file.fileName
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)

  $q.notify({
    type: 'positive',
    message: '开始下载文件: ' + file.fileName,
  })
}

// 确认删除
function confirmDelete(id) {
  $q.dialog({
    title: '确认删除',
    message: '确定要删除该文件吗？此操作不可恢复！',
    cancel: true,
    persistent: true,
  }).onOk(() => {
    // 这里应该是实际的API调用
    $q.notify({
      type: 'positive',
      message: '文件已删除',
    })
    loadFiles()
  })
}

// 上传相关方法
function startUpload() {
  if (uploader.value) {
    uploader.value.upload()
  }
}

function onRejected(rejectedEntries) {
  $q.notify({
    type: 'negative',
    message: `有 ${rejectedEntries.length}  个文件不符合要求`,
  })
}

function onUploaded(info) {
  const response = JSON.parse(info.xhr.response)
  if (response.success) {
    $q.notify({
      type: 'positive',
      message: '文件上传成功',
    })
    uploadDialog.value = false
    loadFiles()
  } else {
    $q.notify({
      type: 'negative',
      message: response.message || '文件上传失败',
    })
  }
}
</script>

<style lang="scss" scoped>
.q-table {
  thead tr th {
    font-weight: bold;
    background-color: #f5f5f5;
  }

  tbody tr:hover {
    background-color: #f5f5f5;
  }
}

.q-uploader {
  border: 1px dashed #ccc;
  border-radius: 4px;

  &__header {
    background-color: #f5f5f5;
    padding: 8px;
  }
}

.full-height {
  height: calc(100vh - 50px);
}
</style>
